#pragma once

#include <libusb-1.0/libusb.h> 
#include <stdio.h>
#include <pthread.h>
#include <errno.h>

#define C_NONE    "\033[m"   
#define C_RED     "\033[0;32;31m"   
#define C_LRED    "\033[1;31m"   
#define C_GREEN   "\033[0;32;32m"   
#define C_LGREEN  "\033[1;32m"  
#define C_BLUE    "\033[0;32;34m"  
#define C_LBLUE   "\033[1;34m"  
#define C_GRAY    "\033[1;30m"  
#define C_LGRAY   "\033[0;37m"  
#define C_CYAN    "\033[0;36m"  
#define C_LCYAN   "\033[1;36m"  
#define C_PURPLE  "\033[0;35m"  
#define C_LPURPLE "\033[1;35m"  
#define C_BROWN   "\033[0;33m"  
#define C_LBROWN  "\033[1;33m"  
#define C_YELLOW  "\033[1;33m"  
#define C_WHITE   "\033[1;37m" 


typedef enum{
    emEnum = 0,
    emOpening
}USB_STATUS;

class TestLibusb{
public:
    TestLibusb();
    ~TestLibusb();

    int init();

    // 列出系统所有的USB设备.
    // 包括：bus number. device number, vid, pid, product info
    int list_devices(void);

    //根据VID:PID，打印特定USB设备的描述符
    int get_descriptor_with_vid_pid(int vid, int pid);

    int open_with_vid_pid(int vid, int pid);

    void close();

    int test();
    
    static void* usb_monitor_thread(void* arg);
    //不要在回调函数中调用可能阻塞的操作，否则可能造成libusb的其他函数执行失败
    static int hotplug_callback(
            struct libusb_context *ctx,
            struct libusb_device *device,
            libusb_hotplug_event event,
            void *user_data);

    // 注册热插拔事件, 成功返回0
    int register_hotplug_callback(int vid = LIBUSB_HOTPLUG_MATCH_ANY, 
                                  int pid = LIBUSB_HOTPLUG_MATCH_ANY);
    // 取消热插拔事件
    void deregister_hotplug_callback();


    // 待完成
    int  bulk_send(char *buf, int num);
    int  interrupt_send(char *buf, int num);
    void *bulk_rev_thread(void *arg);
    void *interrupt_rev_thread(void *arg);
    int  LIBUSB_CALL usb_event_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data);

private:
    int read_debug_info(int nMsgType, char* pBuffer, unsigned int nLen);
    int write_debug_info(int nMsgType, char* pBuffer, unsigned int nLen);

    void print_devs(libusb_device **devs, ssize_t cnt);
    //打印USB设备的描述符
    int  print_descriptor(ssize_t index, libusb_device *dev);
    void print_device(libusb_device *dev, struct libusb_device_descriptor *desc);
    void print_interface(const struct libusb_interface *interface);
    void print_configuration(struct libusb_config_descriptor *config);
    void print_altsetting(const struct libusb_interface_descriptor *interface);
    void print_endpoint(const struct libusb_endpoint_descriptor *endpoint);

    // 待完成
    int  str2hex(char *hex);
    void hex2str(unsigned char *pbDest, unsigned char *pbSrc, ushort nLen);
    int  save_to_file(FILE *file_stream, unsigned char *data, int length);
    void sigint_handler(int sig);

private:
    libusb_context *m_ctx;

    libusb_device_handle* m_handle;

    bool                           m_usb_monitor_running;
    pthread_t                      m_usb_monitor_thread_id;
    libusb_hotplug_callback_handle m_hotplug_callback_handle;

    USB_STATUS m_usb_status;
};

